package org.example.commodity.activity.service;

import cn.hutool.core.util.ObjectUtil;
import org.example.commodity.activity.entity.ActivityInfo;
import org.example.commodity.activity.entity.CommodityActivitySpecSku;
import org.example.commodity.activity.entity.CommodityActivityVirtualCard;
import org.example.commodity.activity.entity.CommoditySkuActivityAttrDto;
import org.example.commodity.activity.exception.CommodityActivityException;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

@Slf4j
public abstract class BaseCommodityActivityProcessor<T extends ActivityInfo> {

    protected final BaseCommodityActivityRedisService<T> redisService;

    protected BaseCommodityActivityProcessor(BaseCommodityActivityRedisService<T> redisService) {
        this.redisService = redisService;
    }

    protected abstract String getActivityType();
    protected abstract  List<CommodityActivitySpecSku> listActivityCommoditySku(Long commodityId);
    protected abstract List<CommodityActivityVirtualCard> listActivityCommodityVirtualCard(Long commodityId);
    protected CommoditySkuActivityAttrDto getActivityAttr(Long commoditySkuId) {
        ActivityInfo activity = this.redisService.getActivityInfo(commoditySkuId);
        if (ObjectUtil.isNull(activity)) {
            return null;
        }
        return new CommoditySkuActivityAttrDto()
                .setActivityId(activity.getId())
                .setStartTime(activity.getStartTime())
                .setEndTime(activity.getEndTime())
                .setActivityPrice(activity.getActivityPrice())
                .setSalesRestriction(activity.getSalesRestriction())
                .setActivityStocks(activity.getActivityStocks())
                .setRemainingStocks(redisService.getCommodityStocks(activity.getId(),commoditySkuId))
                .setVirtualSalesVolume(activity.getVirtualSalesVolume());
    }

    protected abstract Integer getActivityTimeOut();

    public final void decreaseActivityRedisStocks(Long activityId, Long commoditySkuId, Integer quantity) {
        if (redisService.getLock()){
            try {
                Integer commodityStocks = redisService.getCommodityStocks(activityId, commoditySkuId);
                if (ObjectUtil.isNull(commodityStocks)) {
                    throw new CommodityActivityException("商品关联秒杀活动不存在或已结束");
                } else {
                    if (commodityStocks - quantity < 0) {
                        throw new CommodityActivityException("商品库存不足");
                    }
                    redisService.addActivityStocks(activityId, commoditySkuId, quantity);
                }
            }finally {
                redisService.unLock();
            }
        }else{
            decreaseActivityRedisStocks(activityId,commoditySkuId,quantity);
        }

    }
    public final void increaseActivityRedisStocks(Long activityId, Long commoditySkuId, Integer quantity) {
        if (redisService.getLock()){
            try{
                Integer commodityStocks = redisService.getCommodityStocks(activityId,commoditySkuId);
                if (ObjectUtil.isNull(commodityStocks)) {
                    log.info("商品{}暂无秒杀活动", commoditySkuId);
                } else {
                    redisService.addActivityStocks(activityId, commoditySkuId, -1 * quantity);
                }
            }finally {
                redisService.unLock();
            }
        }else{
            increaseActivityRedisStocks(activityId,commoditySkuId,quantity);
        }
    }


    public final Long getCustomerPurchaseNumber(Long commoditySkuId, Long customerId) {
        return redisService.getCustomerPurchaseNumber(customerId, commoditySkuId);
    }

    protected abstract int decreaseActivityStocks(Long activityId, Integer quantity);

    public final void addCustomerPurchaseNumber(Long commoditySkuId, Long customerId, Integer quantity) {
        redisService.customerPurchase(customerId, commoditySkuId, quantity);
    }
}
